package tk0084.dev.google.quiz.lite;

import java.util.Arrays;

public class Puzzle extends Thread{

	private final int _col;
	private final int _row;
	private final String _initialChars;

	public static char BLOCK = '=';
	public static char EMPTY = '0';
	private char[] _finalChars;

	private PuzzleStrategy _strategy;
	private Integer _md;

	private String _answer;
	
	public Puzzle(String initialChars, int row, int col) {
		this._initialChars = initialChars;
		this._row = row;
		this._col = col;

		_finalChars = createEndChars();
		createMinOrder();
	}

	@Override
	public void run(){
		_answer = unpuzzle();
	}
	
	public String unpuzzle() {
//		System.out.println(getMd() + " " + getRow() + "," + getCol() + "," + getInitialChars());
//		return "";
		 return _strategy.unpuzzle(this);
	}

	private char[] createEndChars() {
		char[] finalChars = _initialChars.replaceAll(String.valueOf(BLOCK), "").replaceAll(String.valueOf(EMPTY), "").toCharArray();
		Arrays.sort(finalChars);

		char[] ret = new char[_initialChars.length()];

		for (int initialCharIndex = 0, finalCharIndex = 0; initialCharIndex < _initialChars.length() - 1; initialCharIndex++) {
			final char c = _initialChars.charAt(initialCharIndex);
			if (c == BLOCK) {
				ret[initialCharIndex] = BLOCK;
			} else {
				ret[initialCharIndex] = finalChars[finalCharIndex++];
			}
		}
		ret[_initialChars.length() - 1] = EMPTY;
		return ret;
	}

	public void createMinOrder() {
		int minOrder = _row + _col - 2;
		int md = 0;

//		System.out.println(_initialChars);
		String finalChar = String.valueOf(_finalChars);
		for (char fromChar : _initialChars.toCharArray()) {
			if (fromChar == BLOCK || fromChar == EMPTY) {
				continue;
			}

			int fromIndexOf = _initialChars.indexOf(fromChar);
			int fromRowIndex = fromIndexOf / _row;
			int fromColIndex = fromIndexOf % _row;

			int toIndexOf = finalChar.indexOf(fromChar);
			int toRowIndex = toIndexOf / _row;
			int toColIndex = toIndexOf % _row;

			int mvRow = Math.abs(fromRowIndex - toRowIndex);
			int mvCol = Math.abs(fromColIndex - toColIndex);

//			System.out.println(fromChar + " from:" + fromRowIndex + "," + fromColIndex + " to:" + toRowIndex + "," + toColIndex + " mvRow:" + mvRow + " mvCol" + mvCol);

			if ((mvRow + mvCol) < minOrder) {
				minOrder = mvRow + mvCol;
			}
			md += (mvRow + mvCol);
		}

		_md = md;
	}

	public char[] getFinalChars() {
		return _finalChars;
	}

	public String getInitialChars() {
		return _initialChars;
	}

	public int getCol() {
		return _col;
	}

	public int getRow() {
		return _row;
	}

	public boolean isEndState(char[] stateChar) {
		return Arrays.equals(_finalChars, stateChar);
	}

	public void setStrategy(PuzzleStrategy _strategy) {
		this._strategy = _strategy;
	}

	public Integer getMd() {
		return _md;
	}

	public boolean isUnppuzled() {
		return _answer != null && _answer.trim().length() > 0;
	}

	public String getAnswer() {
		return _answer;
	}

	public void setAnswer(String answer) {
		this._answer = answer;
	}
}
